﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Xml.Serialization;


namespace System
{
    public static class StringExtension
    {
        /// <summary>
        /// Takes a xml string and deserializes it back to a object of a type.
        /// </summary>
        /// <typeparam name="T">The type of the members of values.</typeparam>
        /// <param name="strValue">Current String</param>
        /// <returns>returns a deserialized object of the type of T.</returns>
        public static T FromXML<T>(this string strValue)
        {
            using (TextReader textReader = new StringReader(strValue))
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
                return xmlSerializer.Deserialize(textReader).ToType<T>();
            }
        }

        /// <summary>
        /// Takes a JSON string and deserializes it back to a object of a type.
        /// </summary>
        /// <typeparam name="T">The type of the members of values.</typeparam>
        /// <param name="strValue">Current String</param>
        /// <returns>return a deserialized object of the type of T.</returns>
        public static T FromJSON<T>(this string strValue)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            return serializer.Deserialize<T>(strValue);
        }

        /// <summary>
        /// Takes a JSON2 string and deserializes it back to a object of a type.
        /// </summary>
        /// <typeparam name="T">The type of the members of values.</typeparam>
        /// <param name="strValue">Current String</param>
        /// <returns>returns a deserialized object of the type of T.</returns>
        public static T FromJSON2<T>(this string strValue)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(T));

            using (MemoryStream ms = new MemoryStream())
            {
                ms.Write(Encoding.UTF8.GetBytes(strValue), 0, strValue.Length);

                return (T)json.ReadObject(ms);
            }
        }

        /// <summary>
        /// Takes a string and encodes it to a Base64 string.
        /// </summary>
        /// <param name="strValue">Current String</param>
        /// <returns>Base64 encode string.</returns>
        public static string ToBase64(this string strValue)
        {
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(strValue));
        }

        /// <summary>
        /// Takes a Base64 string and decodes it to a string.
        /// </summary>
        /// <param name="strValue">Current String</param>
        /// <returns>string of the decoded string.</returns>
        public static string FromBase64(this string strValue)
        {
            return System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(strValue));
        }

        /// <summary>
        /// Parses string to System.int
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.int of the string. returns 0 if string is null or not a number.</returns>
        public static int ParseInt(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0;

            int icon = 0;

            int.TryParse(strValue, out icon);

            return icon;
        }

        /// <summary>
        /// Parses string to System.Int32
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.Int32 of the string. returns 0 if string is null or not a number.</returns>
        public static Int32 ParseInt32(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0;

            Int32 icon = 0;

            Int32.TryParse(strValue, out icon);

            return icon;
        }

        /// <summary>
        /// Parses string to System.Int64
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.Int64 of the string. returns 0 if string is null or not a number.</returns>
        public static Int64 ParseInt64(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0;

            Int64 icon = 0;

            Int64.TryParse(strValue, out icon);

            return icon;
        }

        /// <summary>
        /// Parses string to System.short
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.short of the string. returns 0 if string is null or not a number.</returns>
        public static short ParseShort(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0;

            short stret = 0;
            
            short.TryParse(strValue, out stret);

            return stret;
        }

        /// <summary>
        /// Parses string to System.long
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.long of the string. returns 0 if string is null or not a number.</returns>
        public static long ParseLong(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0;

            long lngRet = 0;

            long.TryParse(strValue, out lngRet);

            return lngRet;
        }

        /// <summary>
        /// Parses string to System.double
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.double of the string. returns 0 if string is null or not a number.</returns>
        public static double ParseDouble(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0d;

            double dblRet = 0d;

            Double.TryParse(strValue, out dblRet);

            return dblRet;
        }

        /// <summary>
        /// Parses string to System.decimal
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns>System.decimal of the string. returns 0 if string is null or not a number.</returns>
        public static decimal ParseDecimal(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return 0;

            decimal dmlRet = 0;

            Decimal.TryParse(strValue, out dmlRet);

            return dmlRet;
        }

        /// <summary>
        ///  Value can be 1, 0, true or false as strings
        /// </summary>
        /// <param name="strValue">Must be a string of atleast 1, 0, true or false</param>
        /// <returns></returns>
        public static bool ParseBool(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return false;
            if (strValue.Length == 1 && Char.IsNumber(strValue, 0))
            {
                if (strValue.CompareTo("1") == 0) return true;
            }

            bool boolRet = false;

            bool.TryParse(strValue, out boolRet);

            return boolRet;
        }

        /// <summary>
        ///  Value can be 1, 0, true or false as strings
        /// </summary>
        /// <param name="strValue">Must be a string of atleast 1, 0, true or false</param>
        /// <returns></returns>
        public static Boolean ParseBoolean(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) return false;
            if (strValue.Length == 1 && Char.IsNumber(strValue, 0))
            {
                if (strValue.CompareTo("1") == 0) return true;
            }

            Boolean boolRet = false;

            Boolean.TryParse(strValue, out boolRet);

            return boolRet;
        }

        /// <summary>
        /// Parses string to System.DateTime
        /// </summary>
        /// <param name="strValue">Current string</param>
        /// <returns></returns>
        public static DateTime ParseDateTime(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue)) throw new FormatException("Can't Parse string to DateTime. String Null Or Empty.");

            DateTime d;

            if (DateTime.TryParse(strValue, out d) == false)
                throw new FormatException("Can't Parse string to DateTime. Invalid format.");

            return d;
        }

        /// <summary>
        /// Checks for String.Empty. If true than sets it to null.
        /// </summary>
        /// <param name="strValue"></param>
        /// <returns></returns>
        public static string ToNullIfEmpty(this string strValue)
        {
            if (String.IsNullOrEmpty(strValue))
                return null;

            return strValue;
        }

        /// <summary>
        /// Checks for null. If true than sets it to String.Empty
        /// </summary>
        /// <param name="strValue"></param>
        /// <returns></returns>
        public static string ToEmptyIfNull(this string strValue)
        {
            if (strValue == null)
                return String.Empty;

            return strValue;
        }
    }
}
